/**
 * FireFly (2011)
 */
package com.firefly.kernel.plugins.event;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;

import com.firefly.kernel.spi.event.IKernelEvent;
import com.firefly.kernel.spi.event.IKernelEventEmitter;
import com.firefly.kernel.spi.event.IKernelEventFilter;
import com.firefly.kernel.spi.event.IKernelEventListener;
import com.firefly.logging.Logger;

/**
 * 抽象核心事件触发对象
 * 
 * @version 1.0 2011-1-2
 * @author lexloo(lexloo@gmail.com)
 * @since FireFly 1.0
 */
public abstract class AbstractEventEmitter implements IKernelEventEmitter {
	/** 日志记录器 */
	private static final Logger log = Logger.getLogger(AbstractEventEmitter.class);
	/** 空参数 */
	protected static final Object NULL = new Object();
	/** 空过滤器 */
	protected static final IKernelEventFilter NULL_FILTER = new IKernelEventFilter() {

		@Override
		public boolean wantEvent(IKernelEvent event, Object handback) {
			return false;
		}
	};

	/** 注册信息： Map<filter, Map<handback, List<listener>>> */
	protected Map<IKernelEventFilter, Map<Object, List<IKernelEventListener>>> eventListenerRegistry = new ConcurrentHashMap<IKernelEventFilter, Map<Object, List<IKernelEventListener>>>();

	/** 序列号 */
	private final AtomicLong emitterSequence = new AtomicLong();

	/**
	 * 是否包含监听器
	 * 
	 * @return 包含监听器则为true
	 */
	public boolean hasListeners() {
		return eventListenerRegistry.isEmpty() == false;
	}

	/**
	 * 创建核心事件对象
	 * 
	 * @param type
	 *            事件类型
	 * @param context
	 *            上下文
	 * @return 核心对象事件
	 */
	public IKernelEvent createEvent(String type, Object context) {
		return new AbstractEvent(this, type, nextEmitterSequence(), System.currentTimeMillis(), context);
	}

	@Override
	public void registerListener(IKernelEventListener listener, IKernelEventFilter filter, Object handback) {
		IKernelEventFilter filterObject = filter == null ? NULL_FILTER : filter;
		Object handbackObject = handback == null ? NULL : handback;

		synchronized (eventListenerRegistry) {
			Map<Object, List<IKernelEventListener>> handbacks = eventListenerRegistry.get(filterObject);
			if (handbacks == null) {
				handbacks = new ConcurrentHashMap<Object, List<IKernelEventListener>>();
				eventListenerRegistry.put(filterObject, handbacks);
			}
			List<IKernelEventListener> listeners = handbacks.get(handbackObject);
			if (listeners == null) {
				listeners = new CopyOnWriteArrayList<IKernelEventListener>();
				handbacks.put(handbackObject, listeners);
			}

			listeners.add(listener);
			if (log.isTraceEnabled())
				log.trace("注册监听器: " + listener + ", 过滤器=" + filter + " handback=" + handback + ",对象=" + this);
		}
	}

	@Override
	public void unregisterListener(IKernelEventListener listener, IKernelEventFilter filter, Object handback) {
		IKernelEventFilter filterObject = filter == null ? NULL_FILTER : filter;
		Object handbackObject = handback == null ? NULL : handback;

		synchronized (eventListenerRegistry) {
			Map<Object, List<IKernelEventListener>> handbacks = eventListenerRegistry.get(filterObject);
			if (handbacks != null) {
				List<IKernelEventListener> listeners = handbacks.get(handbackObject);
				if (listeners != null && listeners.remove(listener)) {
					if (log.isTraceEnabled())
						log.trace("移除监听器: " + listener + "，过滤器=" + filter + " handback=" + handback + "，对象=" + this);
					return;
				}
			}
		}
		throw new IllegalStateException("Listener not registered.");
	}

	@Override
	public void fireKernelEvent(IKernelEvent event) {
		if (log.isTraceEnabled())
			log.trace("对象：%s触发事件:%s", this, event);

		if (eventListenerRegistry.isEmpty() == false) {
			for (Map.Entry<IKernelEventFilter, Map<Object, List<IKernelEventListener>>> h : eventListenerRegistry
					.entrySet()) {
				Map<Object, List<IKernelEventListener>> handbacks = h.getValue();
				if (handbacks != null) {
					IKernelEventFilter filter = null;
					Object filterObject = h.getKey();
					if (filterObject != NULL_FILTER)
						filter = (IKernelEventFilter) filterObject;

					for (Map.Entry<Object, List<IKernelEventListener>> handbackEntry : handbacks.entrySet()) {
						List<IKernelEventListener> listeners = handbackEntry.getValue();

						if (listeners != null) {
							Object handback = handbackEntry.getKey();
							if (handback == NULL)
								handback = null;

							for (IKernelEventListener listener : listeners) {
								try {
									if (filter == null || filter.wantEvent(event, handback))
										fireKernelEvent(listener, event, handback);
								} catch (Throwable t) {
									log.warn("忽略异常: " + t.getMessage());
								}
							}
						}
					}
				}
			}
		}
	}

	/**
	 * 触发事件
	 * 
	 * @param listener
	 *            监听器
	 * @param event
	 *            事件
	 * @param handback
	 *            回调处理
	 */
	private void fireKernelEvent(IKernelEventListener listener, IKernelEvent event, Object handback) {
		listener.onEvent(event, handback);
	}

	/**
	 * 获取下一个序列号
	 * 
	 * @return 序列号
	 */
	protected long nextEmitterSequence() {
		return emitterSequence.getAndIncrement();
	}
}
